package simpletestbed.core;


import java.io.File;


import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import simpletestbed.utils.DateUtils;

public class JavaClassPackage {
	private byte[] readBuf = new byte[8*1024];
	
	public JavaClassPackage() {
	}
	
	public void writeToLocal(DataInputStream dis, String classPath) throws IOException {
		// Skip the root directory
		@SuppressWarnings("unused")
		String fileName = dis.readUTF();
		boolean isDir = dis.readBoolean();
		assert(isDir);
		int numSubFiles = dis.readInt();
		// System.out.println(DateUtils.now()+" "+numSubFiles+" files(or directories) to write");
		for (int i=0; i<numSubFiles; i++) {
			writeClassFiles(dis, classPath);
		}
	}
	
	public byte[] loadFromLocal(String classPath) throws IOException {
		ByteArrayOutputStream byteCodeBuffer = new ByteArrayOutputStream(32*1024);
		DataOutputStream dos = new DataOutputStream(byteCodeBuffer);
		loadClassFiles(classPath, dos);
		byte[] ret =  byteCodeBuffer.toByteArray();
		dos.close();
		byteCodeBuffer.close();
		return ret;
	}
	
	private void writeClassFiles(DataInputStream dis, String parentPath) throws IOException {
		String fileName = dis.readUTF();
		boolean isDir = dis.readBoolean();
		// System.out.println(DateUtils.now()+" Writing "+fileName+" isDir: "+isDir);
		File file = new File(parentPath+"/"+fileName);
		if (isDir) {
			file.mkdir();
			int numSubFiles = dis.readInt();
			//System.out.println(DateUtils.now()+" "+numSubFiles+" files(or directories) to write");
			for (int i=0; i<numSubFiles; i++) {
				writeClassFiles(dis, parentPath+"/"+fileName);
			}
		}
		else {
			FileOutputStream fos = new FileOutputStream(file);
			int fileSize = dis.readInt();
			byte[] fileData = new byte[fileSize];
			dis.readFully(fileData);
			fos.write(fileData);
			fos.close();
		}
	}
	
	private void loadClassFiles(String path, DataOutputStream dos) throws IOException {
		File file  = new File(path);
		// Write file name
		dos.writeUTF(file.getName());
		dos.writeBoolean(file.isDirectory());
		if (file.isDirectory()) {
			File[] subFiles = file.listFiles();
			// Write the number of sub files
			dos.writeInt(subFiles.length);
			for (int i=0; i<subFiles.length; i++) {
				File subFile = subFiles[i];
				loadClassFiles(subFile.getPath(), dos);
			}
		}
		else {
			byte[] fileData = loadOneFile(file);
			dos.writeInt(fileData.length);
			dos.write(fileData);
		}
	}
	
	private byte[] loadOneFile(File file) throws IOException {
		ByteArrayOutputStream os = new ByteArrayOutputStream(8*1024);
		FileInputStream fis = new FileInputStream(file);
		int readBytes = 0;
		while((readBytes=fis.read(readBuf))!= -1) {
			os.write(readBuf, 0,  readBytes);
		}
		fis.close();
		os.flush();
		byte[] fileData = os.toByteArray();
		os.close();
		return fileData;
	}
	
	
}
